package nl.grol.yakshop.web.servlet;

import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import nl.grol.yakshop.binding.MyYakShopModule;
import nl.grol.yakshop.domain.model.CustomerOrder;
import nl.grol.yakshop.domain.model.ProcessedOrder;
import nl.grol.yakshop.domain.model.ProcessedOrderStatus;
import nl.grol.yakshop.domain.repository.Repository;
import nl.grol.yakshop.domain.repository.RepositoryI;
import nl.grol.yakshop.domain.service.OrderProcessor;
import nl.grol.yakshop.domain.service.OrderProcessorI;
import nl.grol.yakshop.util.InvalidInputException;
import nl.grol.yakshop.util.NotFoundException;
import nl.grol.yakshop.web.servlet.json.JsonConverter;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;

@Singleton
@SuppressWarnings("serial")
public class OrderServlet extends BaseJsonServlet {
    private static final Logger LOGGER = Logger.getLogger(OrderServlet.class.getName());

    @Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
    	
    	try {
			/*
			 * Get required service from guice
			 */
			Injector injector = Guice.createInjector(new MyYakShopModule());
			RepositoryI repository = injector.getInstance(Repository.class);
			
			List<ProcessedOrder> orders = repository.getAllProcessedOrders();
	
			/*
			 * Convert response to json
			 */
			String processedOrdersAsJson = JsonConverter.makeJsonProcessedOrders(orders);
	
			/*
			 * Write response
			 */
			writeSuccessResponse( req, resp, 200, processedOrdersAsJson);
			
    	} catch( Exception exc ) {
    		
			LOGGER.warning("Undefined error " + exc.getMessage() );
			/*
			 * Report error
			 */
			writeErrorResponse( req, resp, 500, exc);

    	}


    }
    
    @Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
    	
    	int httpResponseStatus = 500; // internal error
    	
		try {
			
			/*
			 * Extract day from uri
			 */
			Integer dayOffsetSinceShopOpening = extractLastPathSegmentFromRequest(req);

			/*
			 * Parse request body
			 */
			CustomerOrder customerOrder = 
				JsonConverter.readCustomerOrderFromJson( dayOffsetSinceShopOpening, req.getReader() );
			LOGGER.info("Successfully parsed json from request");

			/*
			 * Get required service from guice
			 */
			Injector injector = Guice.createInjector(new MyYakShopModule());
			OrderProcessorI orderProcessor = injector.getInstance(OrderProcessor.class);

			/*
			 * Call business logic
			 */
			ProcessedOrder processedOrder = orderProcessor.processorOrder(customerOrder, dayOffsetSinceShopOpening);
			
			/*
			 * Compose the right http response status depending on processed-order-status
			 */
			if( processedOrder.getOrderStatus() == ProcessedOrderStatus.UNFULLFILLED ) {
				// http response status = not found
				httpResponseStatus = 404;
				throw new NotFoundException("Order could not be fullfilled at all");
				
			} else if( processedOrder.getOrderStatus() == ProcessedOrderStatus.PARTIALLY_FULFILLED ) {
				
				// http response status = partial content
				httpResponseStatus = 206;

			} else { // completely fullfilled
				// http response status = created
				httpResponseStatus = 201;
			}
			
			/*
			 * Convert response to json
			 */
			String processedOrderAsJson = JsonConverter.makeJsonProcessedOrder(processedOrder);

			/*
			 * Write response
			 */
			writeSuccessResponse( req, resp, httpResponseStatus, processedOrderAsJson);

			
		} catch( NotFoundException exc ) {
			
			LOGGER.warning("Order could not be fullfilled " );

			writeErrorResponse( req, resp, httpResponseStatus, exc);

		} catch( InvalidInputException exc ) {
			
			LOGGER.warning("Error parsing day from request " + exc.getMessage() );
			httpResponseStatus = 400; // bad request
			writeErrorResponse( req, resp, httpResponseStatus, exc);

		} catch( Exception exc ) {
			
			LOGGER.warning("Undefined error " + exc.getMessage() );
			exc.printStackTrace();
			/*
			 * Report error
			 */
			writeErrorResponse( req, resp, httpResponseStatus, exc);
	
		}
			
	}
}
